//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#ifndef __ELASTOS_REGISTER_H__
#define __ELASTOS_REGISTER_H__

//
// PSR
//
#define PSR_FLAG_MASK   0xf0000000
#define PSR_FLAG_N      __32BIT(31)
#define PSR_FLAG_Z      __32BIT(30)
#define PSR_FLAG_C      __32BIT(29)
#define PSR_FLAG_V      __32BIT(28)

#define PSR_I           __32BIT(7)
#define PSR_F           __32BIT(6)

#define PSR_T           __32BIT(5)

#define PSR_MODE_MASK   0x0000001f
#define PSR_MODE_USR    0x00000010
#define PSR_MODE_FIQ    0x00000011
#define PSR_MODE_IRQ    0x00000012
#define PSR_MODE_SVC    0x00000013
#define PSR_MODE_ABT    0x00000017
#define PSR_MODE_UND    0x0000001b
#define PSR_MODE_SYS    0x0000001f

#if defined(_GNUC)

INLINE void Cli()
{
    ASM("mrs    r0, cpsr;"
        "orr    r0, r0, %0;"
        "msr    cpsr_c, r0;"
        : :"i"(PSR_I | PSR_F) :"r0");
}

INLINE void Sti()
{
    ASM("mrs    r0, cpsr;"
        "and    r0, r0, %0;"
        "msr    cpsr_c, r0;"
        : :"i"(~(PSR_I | PSR_F)) :"r0");
}

INLINE uint32_t SaveFlagsAndCli()
{
    uint32_t uFlags;
    ASM("mrs    %0, cpsr;"
        "orr    r0, %0, %1;"
        "msr    cpsr_c, r0;"
        :"=r"(uFlags) :"i"(PSR_I | PSR_F) :"r0");

//    TIMEPEG_DISABLE_INTERRUPT

    return uFlags;
}

INLINE uint32_t GetCPSR()
{
    uint32_t cpsr;
    ASM("mrs    %0, cpsr;"
        :"=r"(cpsr));
    return cpsr;
}

//INLINE void SetCPSR(uint32_t cpsr)
//{
//    ASM("mrs    cpsr, %0;"
//        :"=r"(cpsr));
//}

#elif defined(_EVC)

EXTERN_C void Cli();
EXTERN_C void Sti();
EXTERN_C uint32_t SaveFlagsAndCli();
EXTERN_C uint32_t GetCPSR();
//EXTERN_C void SetCPSR(uint32_t cpsr);

#else

#error Unknown C++ compiler

#endif // defined(_GNUC)

INLINE void RestoreIF(uint_t uFlags)
{
//    TIMEPEG_RESTORE_INTERRUPT
    if (0 == (uFlags & (PSR_I | PSR_F))) Sti();
}

#define IS_IN_USER_MODE(pContext) \
        (PSR_MODE_USR == ((pContext)->cpsr & PSR_MODE_MASK))

#define IS_IN_KERNEL_MODE(pContext) \
        (!IS_IN_USER_MODE(pContext))

#endif //__ELASTOS_REGISTER_H__
